import { Tool } from '../../../Tool';

class TwoPointPolyline {
	constructor(dataSource, firstPoint) {
		var _that = this;
		function update() {
			return [firstPoint, _that.endPoint];
		}
		this.dataSource = dataSource;
		this.firstPoint = Cesium.Cartesian3.clone(firstPoint);
		this.endPoint = Cesium.Cartesian3.clone(firstPoint);
		this.entity = dataSource.entities.add({
			polyline: {
				positions: new Cesium.CallbackProperty(update, false),
				material: Cesium.Color.CHARTREUSE,
				depthFailMaterial: Cesium.Color.CHARTREUSE,
				width: 2
			}
		});
	}

	destroy() {
		this.dataSource.entities.remove(this.entity);
	}
}
class ThreePointPolygon {
	constructor(dataSource, point1, point2) {
		var _that = this;
		function update() {
			return [point1, point2, _that.endPoint, point1];
		}
		this.dataSource = dataSource;
		this.point1 = point1;
		this.point2 = point2;
		this.endPoint = Cesium.Cartesian3.clone(point1);
		this.entity = dataSource.entities.add({
			polyline: {
				positions: new Cesium.CallbackProperty(update, false),
				fill: false,
				material: Cesium.Color.CHARTREUSE,
				outline: true,
				outlineColor: Cesium.Color.CHARTREUSE,
				outlineWidth: 2
			}
		});
	}

	destroy() {
		this.dataSource.entities.remove(this.entity);
	}
}
/**
 * 面剖切
 */
export class ClipByPointsTool extends Tool {
	constructor(viewer, params, ...args) {
		super(arguments);
		this.viewer = viewer;
		this.mode = params.mode ?? 0; // 0 - 绘制三点剖切， 1 - 垂面剖切， 2 - 水平面剖切
		this.clipLayerLimited = params.limited || [];
		this.dataSource = new Cesium.CustomDataSource('fe-clipbyplane');
		this.viewer.dataSources.add(this.dataSource);
		this.positions = [];
		this.polylinePosition = [];
		this.viewer.scene.layers.layerQueue.forEach((item) => {
			item.selectEnabled = false;
			item.releaseSelection();
		});
	}

	setClipPlane(point1, point2, point3) {
		for (const layer of this.clipLayers) {
			layer.setCustomClipPlane(point1, point2, point3);
		}
	}

	clearClipPlane() {
		for (const layer of this.clipLayers) {
			layer.clearCustomClipBox();
		}
	}

	start() {
		const _that = this;
		this.clipLayers = this.viewer.scene.layers.layerQueue;
		if (this.clipLayerLimited.length > 0) {
			this.clipLayers = [];
			for (const name of this.clipLayerLimited) {
				const layer = this.viewer.scene.layers.find(name);
				layer && this.clipLayers.push(layer);
			}
		}
		this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
		switch (this.mode) {
			case 0: {
				this.handler.setInputAction((e) => {
					const position = _that.viewer.scene.pickPosition(e.position);
					_that.positions.push(position);
					if (_that.positions.length === 1) {
						_that.polyline = new TwoPointPolyline(_that.dataSource, position);
					} else if (_that.positions.length === 2) {
						_that.polyline.destroy();
						_that.polygon = new ThreePointPolygon(
							this.dataSource,
							_that.positions[0],
							_that.positions[1]
						);
					} else if (_that.positions.length === 3) {
						_that.polygon.destroy();
						_that.setClipPlane(..._that.positions);
						_that.handler = _that.handler.destroy();
					}
				}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
				this.handler.setInputAction((e) => {
					if (_that.positions.length === 1) {
						_that.polyline.endPoint = _that.viewer.scene.pickPosition(e.endPosition);
					} else if (_that.positions.length === 2) {
						_that.polygon.endPoint = _that.viewer.scene.pickPosition(e.endPosition);
					}
				}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
				break;
			}
			case 1: {
				this.handler.setInputAction((e) => {
					const position = _that.viewer.scene.pickPosition(e.position);
					_that.positions.push(position);
					if (_that.positions.length === 1) {
						_that.polyline = new TwoPointPolyline(_that.dataSource, position);
					} else if (_that.positions.length === 2) {
						_that.polyline.destroy();
						const carto = Cesium.Cartographic.fromCartesian(position);
						const lon = Cesium.Math.toDegrees(carto.longitude);
						const lat = Cesium.Math.toDegrees(carto.latitude);
						const height = carto.height;
						const point3 = Cesium.Cartesian3.fromDegrees(lon, lat, height - 1);
						_that.positions.push(point3);
						_that.setClipPlane(..._that.positions);
						_that.handler = _that.handler.destroy();
					}
				}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
				this.handler.setInputAction((e) => {
					if (_that.positions.length === 1) {
						_that.polyline.endPoint = _that.viewer.scene.pickPosition(e.endPosition);
					}
				}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
				break;
			}
			case 2: {
				this.handler.setInputAction((e) => {
					const point1 = _that.viewer.scene.pickPosition(e.position);
					const carto = Cesium.Cartographic.fromCartesian(point1);
					const lon = Cesium.Math.toDegrees(carto.longitude);
					const lat = Cesium.Math.toDegrees(carto.latitude);
					const height = carto.height;
					const point2 = Cesium.Cartesian3.fromDegrees(
						lon >= 0 ? lon - 0.0001 : lon + 0.0001,
						lat,
						height
					);
					const point3 = Cesium.Cartesian3.fromDegrees(
						lon,
						lat >= 0 ? lat - 0.0001 : lat + 0.0001,
						height
					);
					_that.clearClipPlane();
					_that.setClipPlane(point1, point2, point3);
				}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
				break;
			}
		}
	}

	cancel() {
		this.clearClipPlane();
		this.handler = this.handler && this.handler.destroy();
		this.dataSource.entities.removeAll();
		this.viewer.dataSources.remove(this.dataSource);
		this.viewer.scene.layers.layerQueue.forEach((item) => {
			item.selectEnabled = true;
		});
		return super.cancel();
	}
}
ClipByPointsTool.toolId = 'ClipByPointsTool';
